package com.rock.app.controller;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.eova.aop.AopContext;
import com.eova.common.utils.xx;
import com.eova.model.EovaLog;
import com.eova.model.MetaObject;
import com.eova.service.sm;
import com.eova.template.common.util.TemplateUtil;
import com.eova.widget.WidgetManager;
import com.jfinal.core.Controller;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.IAtom;
import com.jfinal.plugin.activerecord.Record;
import com.rock.app.base.CompManager;
import com.rock.app.base.MetaApiUtil;
import com.rock.app.base.OpenConsts;
import com.rock.app.base.OpenControllerBase;
import com.rock.sys.config.RockConst;
import com.rock.sys.global.RoleAppBindIntercept;
import com.rock.sys.model.TSApp;
import com.rock.sys.model.TSAppRole;
import com.rock.sys.model.TSPage;
import com.rock.sys.model.TSPageComp;
import com.rock.sys.model.TUser;
import com.rock.sys.util.RockUtil;

import cn.hutool.core.util.StrUtil;

public class AppCommonController extends OpenControllerBase {

	final Controller ctrl = this;
	/** 元对象业务拦截器 **/
	protected RoleAppBindIntercept intercept = null;
	/** 异常信息 **/
	private String errorInfo = "";

	public void index() {

	}

	/**
	 * 获取app所有角色
	 */
	public void getAppRoles() {

		// 查询非默认角色
		List<TSAppRole> roles = TSAppRole.dao.find("select * from t_s_app_role where app_id=? and is_default='0'",
				this.getCurrentApp().getId());
		
		List<TSAppRole> rolesRe = new ArrayList<TSAppRole>();
		//如果绑定元数据编码为空，则置为系统默认的编码
		roles.forEach(r -> {
			if(StrUtil.isBlank(r.getMetaCode())) {
				r.setMetaCode(RockConst.APP_ROLE_DEFAULT_META_CODE);
			}
			rolesRe.add(r);
		});

		Map<String, Object> resData = new HashMap<String, Object>();
		resData.put("appRoles", rolesRe);

		renderOkDataJson(resData);
	}

	/**
	 * 获取app可注册角色
	 */
	public void getAppRolesReg() {

		// 查询非默认角色
		List<TSAppRole> roles = TSAppRole.dao.find("select * from t_s_app_role where app_id=? and is_open_reg='1'",
				this.getCurrentApp().getId());

		Map<String, Object> resData = new HashMap<String, Object>();
		resData.put("appRegRoles", roles);

		renderOkDataJson(resData);
	}

	/**
	 * APP角色绑定
	 * 
	 * @throws Exception
	 */
	public void bindAppUserRole() throws Exception {

		String metaCode = getPara(0);
		String roleId = getPara(1);
		int currentUserId = this.getLoginedUser().getId();

		String postData = getRawData();
		if (StrUtil.isBlank(metaCode) || StrUtil.isBlank(roleId)) {
			renderFailJson(107, "can not get metaCode or roleId");
			return;
		}

		// 查找当前用户是否已有角色，如果有，说明已经绑定
		int rc = Db.queryInt("select count(1) from t_s_app_user u where u.user_id=? and u.rid is not null",
				currentUserId);
		// 处理绑定用户
		if (rc > 0) {
			renderFailJson("绑定失败，已存在绑定信息，如需更换用户，请先解绑");
			return;
		}

		final MetaObject object = sm.meta.getMeta(metaCode);

		Record r = new Record();
		// 预置归属APP
		r.set("app_id", this.getCurrentApp().getId());
		r.set("user_id", currentUserId);
		r.set("type", 1);
		r.set("rid", roleId);

		// 获取当前操作数据
		MetaApiUtil.buildData(this, object, r, object.getPk(), true);

		intercept = RockUtil.initRoleBindIntercept(object.getBizIntercept());
		// 事务(默认为TRANSACTION_READ_COMMITTED)
		boolean flag = Db.use(object.getDs()).tx(new IAtom() {
			@Override
			public boolean run() throws SQLException {
				try {
					AopContext ac = new AopContext(ctrl, r, object);

					// 绑定前置任务
					if (intercept != null) {
						String msg = intercept.addBefore(ac);
						if (!xx.isEmpty(msg)) {
							errorInfo = msg;
							return false;
						}
						// 必填字段检查
						Map res = MetaApiUtil.checkFieldRequiredAdd(metaCode, r);
						if (!(boolean) res.get("isPass")) {
							errorInfo = res.get("reqCn") + "不能为空";
							return false;
						}
						
						msg = intercept.bindBefore(ac);
						if (!xx.isEmpty(msg)) {
							errorInfo = msg;
							return false;
						}
					}


					if (!xx.isEmpty(object.getTable())) {
						// add table
						// 剥离虚拟字段
						Record t = WidgetManager.peelVirtual(r);
						// 新增绑定记录
						Db.use(object.getDs()).save(object.getTable(), object.getPk(), r);
						// 还原虚拟字段
						r.setColumns(t);

						// 更改app用户角色，需要重新获取user_id，因为在业务处理时可能变更过（例如绑定原来的pc用户）
						Db.update("update t_s_app_user set rid=? where user_id=?", roleId, ac.record.getStr("user_id"));
					}

					// 新增后置任务
					if (intercept != null) {
						String msg = intercept.addAfter(ac);
						if (!xx.isEmpty(msg)) {
							errorInfo = msg;
							return false;
						}
						msg = intercept.bindAfter(ac);
						if (!xx.isEmpty(msg)) {
							errorInfo = msg;
							return false;
						}
					}
				} catch (Exception e) {
					errorInfo = "绑定异常:" + TemplateUtil.buildException(e);
					return false;
				}
				return true;
			}
		});

		// AOP提示信息
		if (!flag) {
			renderFailJson(errorInfo);
			return;
		}

		// 记录新增日志
		EovaLog.dao.info(this, EovaLog.ADD, object.getStr("code"), null);

		errorInfo = null;
		// 新增成功之后
		if (intercept != null) {
			try {
				ArrayList<Record> records = new ArrayList<Record>();
				records.add(r);

				AopContext ac = new AopContext(this, records, object);
				String msg = intercept.addSucceed(ac);
				if (!xx.isEmpty(msg)) {
					errorInfo = msg;
				}
				msg = intercept.bindSucceed(ac);
				if (!xx.isEmpty(msg)) {
					errorInfo = msg;
				}
			} catch (Exception e) {
				errorInfo = TemplateUtil.buildException(e);
				renderFailJson("绑定成功,bindSucceed拦截执行异常!" + errorInfo);
				return;
			}
		}

		renderOkDataJson(errorInfo);
	}

	/**
	 * 解除APP角色绑定
	 * @throws Exception 
	 */
	public void removeAppUserRole() throws Exception {

		int roleId = getInt(0);
		int currentUserId = this.getLoginedUser().getId();
		
		String metaCode = Db.queryStr("select r.meta_code from t_s_app_user u, t_s_app_role r where u.user_id=? and u.rid=r.id",
				currentUserId);

		if(StrUtil.isBlank(metaCode)) {
			//传空，使用默认的角色绑定拦截器
			intercept = RockUtil.initRoleBindIntercept("");
		} else {
			MetaObject object = sm.meta.getMeta(metaCode);
			intercept = RockUtil.initRoleBindIntercept(object.getBizIntercept());
		}
		// 事务(默认为TRANSACTION_READ_COMMITTED)
		boolean flag = Db.tx(new IAtom() {
			@Override
			public boolean run() throws SQLException {
				try {

					// 解除前置任务
					if (intercept != null) {
						String msg = intercept.removeBefore(currentUserId, roleId);
						if (!xx.isEmpty(msg)) {
							errorInfo = msg;
							return false;
						}
					}

					// 执行：删除此app用户的角色信息，即是解除绑定
					Db.update("update t_s_app_user set rid=null where user_id=?", currentUserId);

					// 解除后置任务
					if (intercept != null) {
						String msg = intercept.removeAfter(currentUserId, roleId);
						if (!xx.isEmpty(msg)) {
							errorInfo = msg;
							return false;
						}
					}
				} catch (Exception e) {
					errorInfo = "绑定异常:" + TemplateUtil.buildException(e);
					return false;
				}
				return true;
			}
		});

		// AOP提示信息
		if (!flag) {
			renderFailJson(errorInfo);
			return;
		}
		this.renderOkDataJson(errorInfo);
	}

	/**
	 * 获取页面数据
	 */
	public void getPageData() {

		String pageCode = this.getPara();
		if (StrUtil.isBlank(pageCode)) {
			renderFailJson(107, "can not get pageCode");
			return;
		}

		TSApp app = getAttr(OpenConsts.ATTR_LOGINED_APP);
		TSPage page = TSPage.dao.findByAppIdAndPageCode(app.getId(), pageCode);

		List<TSPageComp> pageCompList = new ArrayList<TSPageComp>();
		if (app != null && page != null) {

			// app角色处理
			List<Record> rs = Db.find("select * from t_s_app_role where app_id=?", app.getId());
			// 1 如果app未配置任何角色，则说明此app不需要区分角色，所有用户都一样，返回所有页面
			if (rs.size() == 0) {
				pageCompList = TSPageComp.dao.findByPageId(page.getId());
			} else {
				TUser user = this.getLoginedUserApi();
				// 存在APP用户信息
				if (user != null) {
					// 取出APP用户角色
					String rid = Db.queryStr("select rid from t_s_app_user where user_id=?", user.getId());

					// 角色非空
					if (!StrUtil.isBlank(rid)) {
						// 取出该角色分配的页面信息
						String sql = "SELECT rid,GROUP_CONCAT(DISTINCT comp_id) cmps from t_s_app_role_comps where rid=? and page_id=? group by rid";
						Record rcs = Db.findFirst(sql, rid, page.getId());
						if (rcs != null) {
							String cmps = rcs.getStr("cmps");
							pageCompList = TSPageComp.dao.find("select * from t_s_page_comp where id in(" + cmps
									+ ") and is_show='1' order by sort_no");
						}
					} else {
						// 角色为空，取该app下的lv级别为0的角色作为默认角色
						String sql = "SELECT rid,GROUP_CONCAT(DISTINCT comp_id) cmps from t_s_app_role_comps,t_s_app_role r "
								+ "where rid=r.id and r.lv='0' and r.app_id=? and page_id=? group by rid";
						Record rcs = Db.findFirst(sql, app.getId(), page.getId());
						if (rcs != null) {
							String cmps = rcs.getStr("cmps");
							pageCompList = TSPageComp.dao.find("select * from t_s_page_comp where id in(" + cmps
									+ ") and is_show='1' order by sort_no");
						}
					}
				} else {
					// 角色为空，取该app下的lv级别为0的角色作为默认角色
					String sql = "SELECT rid,GROUP_CONCAT(DISTINCT comp_id) cmps from t_s_app_role_comps,t_s_app_role r "
							+ "where rid=r.id and r.lv='0' and r.app_id=? and page_id=? group by rid";
					Record rcs = Db.findFirst(sql, app.getId(), page.getId());
					if (rcs != null) {
						String cmps = rcs.getStr("cmps");
						pageCompList = TSPageComp.dao.find("select * from t_s_page_comp where id in(" + cmps
								+ ") and is_show='1' order by sort_no");
					}
				}
			}

		} else {
			renderFailJson("未找到APP页面信息");
			return;
		}

		List<HashMap<String, Object>> pageComps = new ArrayList<HashMap<String, Object>>();
		for (TSPageComp pageComp : pageCompList) {
			pageComps.add(CompManager.buildCompData(this, pageComp));
		}

		Map<String, Object> resData = new HashMap<String, Object>();
		resData.put("appCode", app.getAppCode());
		resData.put("pageCode", pageCode);
		resData.put("pageComps", pageComps);

		renderOkDataJson(resData);
	}

}
